package br.ufc.custom.Graph;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.List;
import java.util.Vector;

public class MetisManager {

	final String inputPath = new File("tmp/input.txt").getAbsolutePath();

	private Graph g;

	public MetisManager(Graph g) {
		super();
		this.g = g;
	}

	public List<Integer> execute(int nparts, int ufactor){
		saveTo();
		runMetis(nparts, ufactor, true);
		return parseOutput(nparts);
	}

	private void saveTo() {		 
		PrintWriter writer;
		try {
			writer = new PrintWriter(inputPath, "UTF-8");
			System.out.println("Input path: " + inputPath);
			writer.println(g.getVerticesSize() + " " + g.getEdgesSize() + " 011 1");
			List<Vertex> vertices = g.getVertices();
			Vertex v = null;
			for(int i = 0; i < g.getVerticesSize(); i++){
				v = vertices.get(i);
				writer.print(v.getWeight() + " ");
				for (Vertex neighbor : v.getNeighbors().keySet()) {
					writer.print((neighbor.getID() + 1) + " " + v.getNeighbors().get(neighbor) +" ");				
				}
				writer.println();
			}		
			writer.close();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}		
	}

	private void runMetis(int nparts, int ufactor){
		runMetis(nparts, ufactor, false);
	}

	private void runMetis(int nparts, int ufactor, boolean debug){

		Process proc;		
		Runtime run = Runtime.getRuntime();	   
		boolean is64bits = System.getProperty("sun.arch.data.model").equals("32") ? false : true;

		String command = is64bits? "./lib/gpmetis64" :"./lib/gpmetis32";		
		command = command + " -ufactor=" + ufactor + " " + inputPath + " " + nparts;
		System.out.println(command);
		try {
			proc = run.exec(command);
			BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream()));
			BufferedReader stdError = new BufferedReader(new InputStreamReader(proc.getErrorStream()));

			System.out.println("Here is the standard output of the command:\n");
			String s = null;
			while ((s = stdInput.readLine()) != null) {
				System.out.println(s);
			}
			System.out.println("Here is the standard error of the command (if any):\n");
			while ((s = stdError.readLine()) != null) {
				System.out.println(s);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private List<Integer> parseOutput(int nparts){
		List<Integer> ret = new Vector<Integer>();

		String outputPath = inputPath + ".part." + nparts;
		System.out.println("Output Path");
		BufferedReader br = null;
		try {
			String sCurrentLine; 
			br = new BufferedReader(new FileReader(outputPath));
			while ((sCurrentLine = br.readLine()) != null) {
				ret.add(Integer.parseInt(sCurrentLine));
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if (br != null)br.close();
			} catch (IOException ex) {
				ex.printStackTrace();
			}
		}
		return ret;
	}	
}
